import { _decorator, AnimationClip, AnimationComponent, Component, Layers, math, Node, Rect, resources, Sprite, SpriteFrame, UITransform, Vec2, Vec3 } from 'cc';
import { MonsterController } from '../view/MonsterController';
import { lvCfg } from '../../config/level';
import { creatureCfg } from '../../config/creature';
const { ccclass, property } = _decorator;
const LOG_TITLE = 'MonsterManager:'

const CREATURE_TEX_ROOT = 'ui/creature/'

const BOUNDARY_OFFSET = 200 //离视口距离
const _playerRect = new Rect()

const SPECIAL_MONSTER_NUM = 100
const SPECIAL_MONSTER_LV = 1

@ccclass('MonsterManager')
class MonsterManager {
    public nodeMonsters: Node = null
    private _pool: {[lv: string]: Node[]} = {}

    updateEnvironment(playerLv: number, playerPos: Vec3, range: Vec2, boundary: Rect, isSpecial = false) {
        const children = this.nodeMonsters.children
        const yMin = playerPos.y - range.y
        const xMin = playerPos.x - range.x
        _playerRect.set(xMin, yMin, range.x * 2, range.y * 2)
        
        const monsterLvNums = {}
        children.forEach(child => {
            monsterLvNums[child.name] = (monsterLvNums[child.name] || 0) + 1
        })

        if (isSpecial) { //神坤时刻
            const curNum = monsterLvNums[SPECIAL_MONSTER_LV] || 0
            const spawnNum = SPECIAL_MONSTER_NUM - curNum
            this.spawnMonsters(SPECIAL_MONSTER_LV, _playerRect, boundary, spawnNum)
            return
        }

        const monsterNums = this.getMonsterConfigs()[playerLv - 1]
        for (let i = 0; i < monsterNums.length; i++) {
            const num = monsterNums[i]
            const curNum = monsterLvNums[i + 1] || 0
            const spawnNum = num - curNum
            this.spawnMonsters(i + 1, _playerRect, boundary, spawnNum)
        }
    }

    spawnMonsters(lv: number, playerBoundary: Rect, mapBoundary: Rect, spawnNum: number) {
        if (spawnNum > 0) {
            for (let j = 0; j < spawnNum; j++) {
                const monster = this.popMonster(lv)
                this.nodeMonsters.addChild(monster)
                let posY = math.randomRange(mapBoundary.yMin + BOUNDARY_OFFSET, mapBoundary.yMax - BOUNDARY_OFFSET)
                let posX = math.randomRange(mapBoundary.xMin + BOUNDARY_OFFSET, mapBoundary.xMax - BOUNDARY_OFFSET)
                if (posY < playerBoundary.yMax && posY > playerBoundary.yMin) {
                    if (posX < playerBoundary.xMax && posX > playerBoundary.xMin) { //在视界内
                        let newPosX = math.randomRangeInt(mapBoundary.xMin + BOUNDARY_OFFSET, playerBoundary.xMin - BOUNDARY_OFFSET)
                        if (posX > mapBoundary.xMax - 300) { //玩家此时在靠右的位置
                            
                        }
                        else if (posX < mapBoundary.xMin + 300) { //玩家此时在靠左的位置
                            newPosX = math.randomRangeInt(playerBoundary.xMax + BOUNDARY_OFFSET, mapBoundary.xMax - BOUNDARY_OFFSET)
                        }
                        posX = newPosX
                    }
                }

                monster.setPosition(posX, posY)
            }
        }
    }

    genMonster(lv: number, isPure = false) { //isPure 不需要Controller来控制
        const cfg = creatureCfg.find(c => c.lv == lv)
        if (!cfg) {
            console.error(LOG_TITLE, '无法找到对应等级怪物的配置:', lv)
            return
        }

        const texPath = CREATURE_TEX_ROOT + cfg.img + '/spriteFrame'
        const node = new Node(lv.toString())
        node.layer = Layers.Enum['Game']
        node.setScale(cfg.scale, cfg.scale)
        node.addComponent(UITransform)

        if (!isPure) {
            node.addComponent(MonsterController).data_speed = cfg.speed
            node.getComponent(MonsterController).data_angleSpeed = cfg.angular
        }

        const sf = resources.get<SpriteFrame>(texPath)
        // if (!sf) {
        //     resources.load(texPath, SpriteFrame, (_, spriteFrame) => {
        //         if (spriteFrame && node.isValid) {
        //             node.addComponent(Sprite).spriteFrame = spriteFrame
        //         }
        //     })
        // }
        // else {
            node.addComponent(Sprite).spriteFrame = sf
        // }

        if (cfg.anim) {
            const comp = node.addComponent(AnimationComponent)
            const clip = resources.get<AnimationClip>('anim/' + cfg.anim)
            comp.defaultClip = clip
            comp.playOnLoad = true
            // comp.play()
            // resources.load(, AnimationClip, (err, clip) => {
            //     if (err) {
            //         console.error(LOG_TITLE, err)
            //     }
            //     else {
            //         if (comp.isValid) { 
            //             comp.defaultClip = clip 
            //         }
            //     }
            // })
        }

        return node
    }

    pushMonster(node: Node) {
        node.removeFromParent()
        const lv = node.name
        const p = this._pool[lv]
        if (!p) {
            this._pool[lv] = [node]
        }
        else {
            p.push(node)
        }

        return
    }

    popMonster(lv: number) {
        const p = this._pool[lv]
        if (!p || p.length == 0) {
            const monster = this.genMonster(lv)
            return monster
        }
        else {
            return p.pop()
        }
    }

    getMonsterConfigs() {
        let storage = localStorage.getItem('Config')
        if (storage) {
            const newCfg = lvCfg.map(v => v.monsters.slice())
            storage = JSON.parse(storage)

            Object.keys(storage).forEach(playerLv => {
                const monsterLvs = storage[playerLv]
                Object.keys(monsterLvs).forEach(lv => {
                    const originValue = newCfg[Number(playerLv) - 1][Number(lv) - 1]
                    if (originValue == undefined) {
                        console.error(LOG_TITLE, '记录的玩家等级和怪物等级有错误:', playerLv, lv)
                    }
                    else {
                        newCfg[Number(playerLv) - 1][Number(lv) - 1] = Math.max(monsterLvs[lv] + newCfg[Number(playerLv) - 1][Number(lv) - 1], 0)
                    }
                })
            })

            return newCfg
        }
        else {
            return lvCfg.map(cfg => cfg.monsters)
        }
    }

    clear() {
        Object.keys(this._pool).forEach(lv => {
            const collection = this._pool[lv]
            collection.forEach(node => {
                node.destroy()
            })
            collection.length = 0
        })
    }
}

export const monsterManager = new MonsterManager()